﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using BLToolkit.DataAccess;
using Devsoft.DB.Models;

namespace Devsoft.Web.Mvc.JqGrid
{
    public static class JqGridExtention
    {
        public static JqGridResponse ToJqGridResponse<T>(this JqGridData<T> entities,object keyselector) where T:IModel
        {
            if (!entities.rows.Any())
            {
                return entities.ToJqGridResponse(null);
            }
            var type = typeof(T);
            var cols = keyselector
                        .GetType()
                        .GetProperties()
                        .Select(x => (Func<T, object>)Delegate.CreateDelegate(typeof (Func<T, object>), null, type.GetProperty(x.Name).GetGetMethod())).ToArray();
            return ToJqGridResponse(entities, null,cols);
        }
        public static JqGridResponse ToJqGridResponse<T>(this JqGridData<T> entities,Func<T, object> idGetter = null,params Func<T,object>[] cols) where T:IModel
        {
            if (!entities.rows.Any())
            {
                return entities.ToResponse(null,null);
            }
            var rowId = 0;
            var first = entities.rows.First();

            if (idGetter == null)
            {
                if (first.HasPrimaryField())
                {
                    idGetter = (x) => x.GetPrimaryValue<object>().ToString();
                }
                else
                {
                    idGetter = (x) => rowId++;
                }    
            }

            if (cols == null || cols.Length == 0) //Display all
            {
                cols = first.GetType()
                            .GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance)
                            .Where(x => !x.GetCustomAttributes(typeof(SqlIgnoreAttribute),true).Any())
                            .Select(x => BuildAccessor<T>(x.GetGetMethod()))
                            .ToArray();
            }
            return entities.ToResponse(idGetter, cols);
        }

        private static Func<T, object> BuildAccessor<T>(MethodInfo method)
        {
            ParameterExpression obj = Expression.Parameter(typeof(T), "obj");
            Expression<Func<T, object>> expr =
                Expression.Lambda<Func<T, object>>(
                    Expression.Convert(
                        Expression.Call(
                            Expression.Convert(obj, method.DeclaringType),
                            method),
                        typeof(object)),
                    obj);

            return expr.Compile();
        }


        public static JqGridResponse ToJqGridResponse<T>(this IEnumerable<T> entities,params Func<T,object>[] cols) where T:IModel
        {
            return entities.ToJqGridData().ToJqGridResponse(cols);
        }

        public static JqGridData<T> ToJqGridData<T>(this IEnumerable<T> entities) where T : IModel
        {
            var tmp = entities.ToList();
            return new JqGridData<T>()
                {
                    page = 1,
                    records = tmp.Count,
                    total = 1,
                    rows = tmp
                };
        }

    }
}
